﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Media;
using System.Windows.Media.Animation;

namespace CPPEI.Coolzon.UI
{
    [XPartIcon("pack://application:,,,/CPPEI.Coolzon.UI;component/Images/PartIcons/选项卡容器.png")]
    [System.ComponentModel.DisplayName("选项卡容器")]
    public partial class TabContainerPart : ControlPart, IPartContainer
    {
        static TabContainerPart()
        {
            DefaultStyleKeyProperty.OverrideMetadata(typeof(TabContainerPart), new FrameworkPropertyMetadata(typeof(TabContainerPart)));

        }

        private Storyboard _activeAnimation;

        private List<TabHeader> _headers;

        public object HeaderContent
        {
            get
            {
                return GetValue(HeaderContentProperty);
            }
            set
            {
                SetValue(HeaderContentProperty, value);
            }
        }

        public static DependencyProperty HeaderContentProperty = DependencyProperty.Register("HeaderContent",
            typeof(object),
            typeof(TabContainerPart),
            null);

        private StackPanel _stackPanel;

        private PartCollection _partCollection;
        private Part _currentPart;
        /// <summary>
        /// 上一个激活的组件，当新组件被激活时，当前的组件变成上一个激活的组件
        /// </summary>
        private Part _lastPart;
        private TabHeader _currentHeader;

        public int ActiveTabIndex { get; private set; }

        #region XProperties

        [Category("Appearance")]
        [DisplayName("切换显示动画时间")]
        [Description("ChildActiveAnimationDuration")]
        [Editor(typeof(XProperty.Editors.XDoubleEditor), typeof(XProperty.XPropertyValueEditor))]
        [XProperty(XPropertyCategory.Appearance, "ChildActiveAnimationDuration", "切换显示动画时间", false)]
        public double XChildActiveAnimationDuration
        {
            get;
            set;
        }

        /// <summary>
        /// Tab页签所在的区域的内部间距 
        /// 默认是10,0,0,0
        /// </summary>
        [Category("Appearance")]
        [DisplayName("Tab标题栏的内部距离")]
        [Description("HeaderBarPadding")]
        [Editor(typeof(XProperty.Editors.XThicknessEditor), typeof(XProperty.XPropertyValueEditor))]
        [XProperty(XPropertyCategory.Appearance, "HeaderBarPadding", "Tab标题栏的内部距离", false)]
        public Thickness XHeaderBarPadding
        {
            get
            {
                return (Thickness)GetValue(XHeaderBarPaddingProperty);
            }
            set
            {
                SetValue(XHeaderBarPaddingProperty, value);
            }
        }

        /// <summary>
        /// 每个tab页签之间的间隔距离，第一个tab页不会受到影响 
        /// 默认-10
        /// </summary>
        [Category("Appearance")]
        [DisplayName("标题的间距")]
        [Description("HeaderSpacing")]
        [Editor(typeof(XProperty.Editors.XDoubleEditor), typeof(XProperty.XPropertyValueEditor))]
        [XProperty(XPropertyCategory.Appearance, "HeaderSpacing", "标题的间距", false)]
        public double XHeaderSpacing
        {
            get;
            set;
        }

        [Category("Appearance")]
        [DisplayName("标题背景图片")]
        [Description("HeaderBackgroundImage")]
        [Editor(typeof(XProperty.Editors.XImageSourceFileEditor), typeof(XProperty.XPropertyValueEditor))]
        [XProperty(XPropertyCategory.Appearance, "HeaderBackgroundImage", "标题背景图片")]
        public ImageSourceFile XHeaderBackgroundImage
        {
            get
            {
                return (ImageSourceFile)GetValue(XHeaderBackgroundImageProperty);
            }
            set
            {
                SetValue(XHeaderBackgroundImageProperty, value);
            }
        }

        [Category("Appearance")]
        [DisplayName("标题高度")]
        [Description("HeaderHeight")]
        [Editor(typeof(XProperty.Editors.XDoubleEditor), typeof(XProperty.XPropertyValueEditor))]
        [XProperty(XPropertyCategory.Appearance, "HeaderHeight", "标题高度")]
        public double XHeaderHeight
        {
            get
            {
                return (double)GetValue(XHeaderHeightProperty);
            }
            set
            {
                SetValue(XHeaderHeightProperty, value);
            }
        }

        [Category("Appearance")]
        [DisplayName("标题宽度")]
        [Description("HeaderWidth")]
        [Editor(typeof(XProperty.Editors.XDoubleEditor), typeof(XProperty.XPropertyValueEditor))]
        [XProperty(XPropertyCategory.Appearance, "HeaderWidth", "标题宽度")]
        public double XHeaderWidth
        {
            get
            {
                return (double)GetValue(XHeaderWidthProperty);
            }
            set
            {
                SetValue(XHeaderWidthProperty, value);
            }
        }

        [Category("Appearance")]
        [DisplayName("标题内边距")]
        [Description("HeaderPadding")]
        [Editor(typeof(XProperty.Editors.XThicknessEditor), typeof(XProperty.XPropertyValueEditor))]
        [XProperty(XPropertyCategory.Appearance, "HeaderPadding", "标题内边距")]
        public Thickness XHeaderPadding
        {
            get
            {
                return (Thickness)GetValue(XHeaderPaddingProperty);
            }
            set
            {
                SetValue(XHeaderPaddingProperty, value);
            }
        }

        [Category("Appearance")]
        [DisplayName("标题前景色")]
        [Description("HeaderForeground")]
        [Editor(typeof(XProperty.Editors.XBrushEditor), typeof(XProperty.XPropertyValueEditor))]
        [XProperty(XPropertyCategory.Appearance, "HeaderForeground", "标题前景色")]
        public BrushEx XHeaderForeground
        {
            get
            {
                return (BrushEx)GetValue(XHeaderForegroundProperty);
            }
            set
            {
                SetValue(XHeaderForegroundProperty, value);
            }
        }

        [Category("Appearance")]
        [DisplayName("标题字体大小")]
        [Description("HeaderFontSize")]
        [Editor(typeof(XProperty.Editors.XDoubleEditor), typeof(XProperty.XPropertyValueEditor))]
        [XProperty(XPropertyCategory.Appearance, "HeaderFontSize", "标题字体大小")]
        public double XHeaderFontSize
        {
            get
            {
                return (double)GetValue(XHeaderFontSizeProperty);
            }
            set
            {
                SetValue(XHeaderFontSizeProperty, value);
            }
        }

        [Category("Appearance")]
        [DisplayName("标题字体")]
        [Description("HeaderFont")]
        [Editor(typeof(XProperty.Editors.XFontFamilyEditor), typeof(XProperty.XPropertyValueEditor))]
        [XProperty(XPropertyCategory.Appearance, "HeaderFont", "标题字体")]
        public FontFamily XHeaderFont
        {
            get
            {
                return (FontFamily)GetValue(XHeaderFontProperty);
            }
            set
            {
                SetValue(XHeaderFontProperty, value);
            }
        }

        #region active
        [Category("Appearance")]
        [DisplayName("Active标题背景图片")]
        [Description("ActiveHeaderBackgroundImage")]
        [Editor(typeof(XProperty.Editors.XImageSourceFileEditor), typeof(XProperty.XPropertyValueEditor))]
        [XProperty(XPropertyCategory.Appearance, "ActiveHeaderBackgroundImage", "Active标题背景图片")]
        public ImageSourceFile XActiveHeaderBackgroundImage
        {
            get
            {
                return (ImageSourceFile)GetValue(XActiveHeaderBackgroundImageProperty);
            }
            set
            {
                SetValue(XActiveHeaderBackgroundImageProperty, value);
            }
        }

        [Category("Appearance")]
        [DisplayName("Active标题高度")]
        [Description("ActiveHeaderHeight")]
        [Editor(typeof(XProperty.Editors.XDoubleEditor), typeof(XProperty.XPropertyValueEditor))]
        [XProperty(XPropertyCategory.Appearance, "ActiveHeaderHeight", "Active标题高度")]
        public double XActiveHeaderHeight
        {
            get
            {
                return (double)GetValue(XActiveHeaderHeightProperty);
            }
            set
            {
                SetValue(XActiveHeaderHeightProperty, value);
            }
        }

        [Category("Appearance")]
        [DisplayName("Active标题宽度")]
        [Description("ActiveHeaderWidth")]
        [Editor(typeof(XProperty.Editors.XDoubleEditor), typeof(XProperty.XPropertyValueEditor))]
        [XProperty(XPropertyCategory.Appearance, "ActiveHeaderWidth", "Active标题宽度")]
        public double XActiveHeaderWidth
        {
            get
            {
                return (double)GetValue(XActiveHeaderWidthProperty);
            }
            set
            {
                SetValue(XActiveHeaderWidthProperty, value);
            }
        }

        [Category("Appearance")]
        [DisplayName("Active标题内边距")]
        [Description("ActiveHeaderPadding")]
        [Editor(typeof(XProperty.Editors.XThicknessEditor), typeof(XProperty.XPropertyValueEditor))]
        [XProperty(XPropertyCategory.Appearance, "ActiveHeaderPadding", "Active标题内边距")]
        public Thickness XActiveHeaderPadding
        {
            get
            {
                return (Thickness)GetValue(XActiveHeaderPaddingProperty);
            }
            set
            {
                SetValue(XActiveHeaderPaddingProperty, value);
            }
        }

        [Category("Appearance")]
        [DisplayName("Active标题前景色")]
        [Description("ActiveHeaderForeground")]
        [Editor(typeof(XProperty.Editors.XBrushEditor), typeof(XProperty.XPropertyValueEditor))]
        [XProperty(XPropertyCategory.Appearance, "ActiveHeaderForeground", "Active标题前景色")]
        public BrushEx XActiveHeaderForeground
        {
            get
            {
                return (BrushEx)GetValue(XActiveHeaderForegroundProperty);
            }
            set
            {
                SetValue(XActiveHeaderForegroundProperty, value);
            }
        }

        [Category("Appearance")]
        [DisplayName("Active标题字体大小")]
        [Description("ActiveHeaderFontSize")]
        [Editor(typeof(XProperty.Editors.XDoubleEditor), typeof(XProperty.XPropertyValueEditor))]
        [XProperty(XPropertyCategory.Appearance, "ActiveHeaderFontSize", "Active标题字体大小")]
        public double XActiveHeaderFontSize
        {
            get
            {
                return (double)GetValue(XActiveHeaderFontSizeProperty);
            }
            set
            {
                SetValue(XActiveHeaderFontSizeProperty, value);
            }
        }

        [Category("Appearance")]
        [DisplayName("Active标题字体")]
        [Description("ActiveHeaderFont")]
        [Editor(typeof(XProperty.Editors.XFontFamilyEditor), typeof(XProperty.XPropertyValueEditor))]
        [XProperty(XPropertyCategory.Appearance, "ActiveHeaderFont", "Active标题字体")]
        public FontFamily XActiveHeaderFont
        {
            get
            {
                return (FontFamily)GetValue(XActiveHeaderFontProperty);
            }
            set
            {
                SetValue(XActiveHeaderFontProperty, value);
            }
        }
        #endregion

        #endregion

        private static void propertyChangedCallback(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            TabContainerPart tabContainerPart = d as TabContainerPart;
            tabContainerPart.Refresh();
        }
        #region Dependency Properties
        public static DependencyProperty XHeaderBarPaddingProperty = DependencyProperty.Register("XHeaderBarPadding",
            typeof(Thickness),
            typeof(TabContainerPart),
            new PropertyMetadata(propertyChangedCallback));

        public static DependencyProperty XHeaderBackgroundImageProperty = DependencyProperty.Register("XHeaderBackgroundImage",
            typeof(ImageSourceFile),
            typeof(TabContainerPart),
            new PropertyMetadata(null, OnXHeaderBackgroundImagePropertyChangedCallback));

        public static DependencyProperty XHeaderHeightProperty = DependencyProperty.Register("XHeaderHeight",
            typeof(double),
            typeof(TabContainerPart),
            new PropertyMetadata(propertyChangedCallback));
        public static DependencyProperty XHeaderWidthProperty = DependencyProperty.Register("XHeaderWidth",
            typeof(double),
            typeof(TabContainerPart),
            new PropertyMetadata(propertyChangedCallback));
        public static DependencyProperty XHeaderPaddingProperty = DependencyProperty.Register("XHeaderPadding",
            typeof(Thickness),
            typeof(TabContainerPart),
            new PropertyMetadata(propertyChangedCallback));
        public static DependencyProperty XHeaderForegroundProperty = DependencyProperty.Register("XHeaderForeground",
            typeof(BrushEx),
            typeof(TabContainerPart),
            new PropertyMetadata(propertyChangedCallback));
        public static DependencyProperty XHeaderFontSizeProperty = DependencyProperty.Register("XHeaderFontSize",
            typeof(double),
            typeof(TabContainerPart),
            new PropertyMetadata(propertyChangedCallback));
        public static DependencyProperty XHeaderFontProperty = DependencyProperty.Register("XHeaderFont",
            typeof(FontFamily),
            typeof(TabContainerPart),
            new PropertyMetadata(propertyChangedCallback));

        private static void OnXHeaderBackgroundImagePropertyChangedCallback(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            TabContainerPart part = d as TabContainerPart;
            for (int index = 0; index < part._headers.Count; index++)
            {
                part._headers[index].XHeaderBackgroundImage = e.NewValue as ImageSourceFile;
            }
            part.Refresh();
        }
        #region active

        public static DependencyProperty XActiveHeaderBackgroundImageProperty = DependencyProperty.Register("XActiveHeaderBackgroundImage",
            typeof(ImageSourceFile),
            typeof(TabContainerPart),
            new PropertyMetadata(null, OnXActiveHeaderBackgroundImagePropertyChangedCallback));
        public static DependencyProperty XActiveHeaderHeightProperty = DependencyProperty.Register("XActiveHeaderHeight",
            typeof(double),
            typeof(TabContainerPart),
            null);
        public static DependencyProperty XActiveHeaderWidthProperty = DependencyProperty.Register("XActiveHeaderWidth",
            typeof(double),
            typeof(TabContainerPart),
            null);
        public static DependencyProperty XActiveHeaderPaddingProperty = DependencyProperty.Register("XActiveHeaderPadding",
            typeof(Thickness),
            typeof(TabContainerPart),
            null);
        public static DependencyProperty XActiveHeaderForegroundProperty = DependencyProperty.Register("XActiveHeaderForeground",
            typeof(BrushEx),
            typeof(TabContainerPart),
            null);
        public static DependencyProperty XActiveHeaderFontSizeProperty = DependencyProperty.Register("XActiveHeaderFontSize",
            typeof(double),
            typeof(TabContainerPart),
            null);
        public static DependencyProperty XActiveHeaderFontProperty = DependencyProperty.Register("XActiveHeaderFont",
            typeof(FontFamily),
            typeof(TabContainerPart),
            null);

        private static void OnXActiveHeaderBackgroundImagePropertyChangedCallback(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            TabContainerPart part = d as TabContainerPart;
            for (int index = 0; index < part._headers.Count; index++)
            {
                part._headers[index].XActiveHeaderBackgroundImage = e.NewValue as ImageSourceFile;
            }
        }
        #endregion

        #endregion

        public TabContainerPart()
        {
            _headers = new List<TabHeader>();

            _stackPanel = new StackPanel();
            _stackPanel.Orientation = Orientation.Horizontal;
            HeaderContent = _stackPanel;

            _partCollection = new PartCollection(this);

            this.XHeaderBarPadding = new Thickness(10, 0, 0, 0);
            this.XHeaderSpacing = -10;

            this.XHeaderHeight = 25;
            this.XActiveHeaderHeight = 25;
            this.XHeaderFontSize = 10;
            this.XHeaderWidth = 100;
            this.XActiveHeaderWidth = 100;
            this.XActiveHeaderFontSize = 12;
            this.XChildActiveAnimationDuration = 1;
        }

        void header_Click(object sender, RoutedEventArgs e)
        {
            TabHeader header = sender as TabHeader;
            if (_currentPart != header.Part)
            {
                int oldIndex = 0;
                int newIndex = 0;
                if (_currentHeader != null)
                {
                    for (int index = 0; index < _headers.Count; index++)
                    {
                        if (_headers[index] == _currentHeader)
                        {
                            oldIndex = index;
                            break;
                        }
                    }
                }

                for (int index = 0; index < _headers.Count; index++)
                {
                    if (_headers[index] == header)
                    {
                        newIndex = index;
                        break;
                    }
                }

                // 将事件发送到EventBus
                Common.EventBus.Instance.Publish(new Event.TabChangeEvent(oldIndex, newIndex, "", this.Name));
            }
        }

        /// <summary>
        /// 选中一个选项卡
        /// </summary>
        /// <param name="newIndex"></param>
        public void SelectTab(int newIndex)
        {
            TabHeader header = _headers[newIndex];

            if (header == _currentHeader)
            {
                // 当前选项卡是激活的不用再切换
                return;
            }

            if (_currentHeader != null)
            {
                Panel.SetZIndex(_currentHeader, 1);
                _currentHeader.IsSelected = false;
                _lastPart = _currentHeader.Part;
            }


            _currentHeader = header;
            if (_currentHeader != null)
            {
                Panel.SetZIndex(_currentHeader, 2);
                _currentHeader.IsSelected = true;
                ActiveTabIndex = newIndex;
            }

            _currentPart = header.Part;
            this.Content = _currentPart;

            #region 淡出动画
            _currentPart.Opacity = 0;
            if (_activeAnimation != null)
            {
                _activeAnimation.Stop();
                _activeAnimation.Remove();
                _activeAnimation = null;
            }
            _activeAnimation = new Storyboard();
            _activeAnimation.Completed += _activeAnimation_Completed;
            DoubleAnimation opacityAnimation = new DoubleAnimation(0, 1, new Duration(TimeSpan.FromSeconds(XChildActiveAnimationDuration)));
            Storyboard.SetTarget(opacityAnimation, _currentPart);
            Storyboard.SetTargetProperty(opacityAnimation, new PropertyPath(UIElement.OpacityProperty));
            _activeAnimation.Children.Add(opacityAnimation);
            _activeAnimation.Begin();
            #endregion
        }

        void _activeAnimation_Completed(object sender, EventArgs e)
        {
            ClockGroup clockGroup = sender as ClockGroup;
            if (clockGroup.CurrentState == ClockState.Filling)
            {
                if (_currentPart != null)
                {
                    _currentPart.Opacity = 1;
                    _currentPart.Active(PartContext);
                    if (_lastPart != null)
                    {
                        _lastPart.Deactive();
                    }
                }
            }
        }

        protected override void OnInit(PartContext context)
        {
            for (int index = 0; index < this._partCollection.Count; index++)
            {
                this._partCollection[index].Init(context);
            }

            base.OnInit(context);
        }

        protected override void OnActive(PartContext context)
        {
            base.OnActive(context);

            if (context.OpenSceneArgs != null
                && context.OpenSceneArgs.GetBool("sys:isresetviewstate"))
            {
                if (_currentPart != null)
                {
                    _currentPart.Deactive();
                    _currentHeader.IsSelected = false;
                }

                if (this._partCollection.Count > 0)
                {
                    _currentPart = this._partCollection[0];
                    _currentHeader = _headers[0];
                    ActiveTabIndex = 0;
                }

                if (_currentHeader != null)
                {
                    Panel.SetZIndex(_currentHeader, 2);
                    _currentHeader.IsSelected = true;
                }

                this.Content = _currentPart;
            }
            else
            {
                if (_currentPart == null)
                {
                    if (this._partCollection.Count > 0 && _currentPart == null)
                    {
                        _currentPart = this._partCollection[0];
                        _currentHeader = _headers[0];
                        ActiveTabIndex = 0;
                    }

                    if (_currentHeader != null)
                    {
                        Panel.SetZIndex(_currentHeader, 2);
                        _currentHeader.IsSelected = true;
                    }

                    this.Content = _currentPart;
                }
            }

            if (_currentPart != null)
            {
                _currentPart.Active(context);
            }
        }

        protected override void OnDeactive(PartContext context)
        {
            if (_activeAnimation != null)
            {
                _activeAnimation.Stop();
                _activeAnimation.Remove();
                _activeAnimation = null;
            }

            if (this._currentPart != null)
            {
                this._currentPart.Deactive();
            }

            base.OnDeactive(context);
        }

        protected override void OnDestory()
        {
            if (_activeAnimation != null)
            {
                _activeAnimation.Stop();
                _activeAnimation.Remove();
                _activeAnimation = null;
            }
            for (int index = 0; index < _headers.Count; index++)
            {
                _headers[index].Part.Destory();
                _headers[index].Part.ParentPart = null;
            }
            _headers.Clear();
            _stackPanel.Children.Clear();

            this.Content = null;


            _partCollection.Clear();
            base.OnDestory();
        }

        protected override void OnReset()
        {
            base.OnReset();

            if (this.ActiveTabIndex != 0)
            {
                #region 选项卡重置到第一个
                if (_currentPart != null)
                {
                    _currentPart.Deactive();
                    _currentHeader.IsSelected = false;
                }

                if (this._partCollection.Count > 0)
                {
                    _currentPart = this._partCollection[0];
                    _currentHeader = _headers[0];
                    ActiveTabIndex = 0;
                }

                if (_currentHeader != null)
                {
                    Panel.SetZIndex(_currentHeader, 2);
                    _currentHeader.IsSelected = true;
                }

                this.Content = _currentPart;
                _currentPart.Active(this.PartContext);
                #endregion
            }

            for (int index = 0; index < this._partCollection.Count; index++)
            {
                this._partCollection[index].Reset();
            }
        }

        protected override void OnRefresh()
        {
            base.OnRefresh();

            if (_currentPart != null)
            {
                _currentPart.Refresh();
            }
        }

        public override UI.Part GetPartAtPoint(Type type, Point pointInRoot, UIElement rootElement)
        {
            if (!XIsVisible)
            {
                return null;
            }
            UI.Part part = null;
            // Point absolutePoint = this.TranslatePoint(new Point(0, 0), rootElement);
            for (int index = 0; index < this._partCollection.Count; index++)
            {
                part = this._partCollection[index].GetPartAtPoint(type, pointInRoot, rootElement);
                if (part != null)
                {
                    return part;
                }
            }
            return base.GetPartAtPoint(type, pointInRoot, rootElement);
        }


        /// <summary>
        /// 测试是否x，y点是否命中了组件实例
        /// </summary>
        /// <param name="pointInScene">场景中的坐标点</param>
        /// <returns></returns>
        public override Data.XHitResult XHitTest(Point pointInScene)
        {
            if (!XIsVisible)
            {
                return new Data.XHitResult(false, null, default(Point));
            }

            Point pos = this.XGetAbsolutePos();
            Size size = this.XGetSize();

            if (pointInScene.X >= pos.X
                && pointInScene.Y >= pos.Y
                && pointInScene.X <= pos.X + size.Width
                && pointInScene.Y <= pos.Y + size.Height)
            {
                for (int index = this._partCollection.Count - 1; index >= 0; index--)
                {
                    Data.XHitResult hitResult = this._partCollection[index].XHitTest(pointInScene);
                    if (hitResult.IsSuccess)
                    {
                        return hitResult;
                    }
                }
                return new Data.XHitResult(true, this, new Point(pointInScene.X - pos.X, pointInScene.Y - pos.Y));
            }
            return new Data.XHitResult(false, null, default(Point));
        }

        /// <summary>
        /// 测试是否x，y点是否命中了组件实例
        /// </summary>
        /// <typeparam name="T">命中的组件必须属于这个类型</typeparam>
        /// <param name="pointInScene">场景中的坐标点</param>
        /// <returns></returns>
        public override Data.XHitResult XHitTest<T>(Point pointInScene)
        {
            if (!XIsVisible)
            {
                return new Data.XHitResult(false, null, default(Point));
            }

            Type type = typeof(T);
            Point pos = this.XGetAbsolutePos();
            Size size = this.XGetSize();

            if (pointInScene.X >= pos.X
                && pointInScene.Y >= pos.Y
                && pointInScene.X <= pos.X + size.Width
                && pointInScene.Y <= pos.Y + size.Height)
            {
                for (int index = this._partCollection.Count - 1; index >= 0; index--)
                {
                    Data.XHitResult hitResult = this._partCollection[index].XHitTest<T>(pointInScene);
                    if (hitResult.IsSuccess)
                    {
                        return hitResult;
                    }
                }
                if (this.GetType() == type || this.GetType().IsSubclassOf(type)
                    || type.IsAssignableFrom(this.GetType()))
                {
                    return new Data.XHitResult(true, this, new Point(pointInScene.X - pos.X, pointInScene.Y - pos.Y));
                }
            }
            return new Data.XHitResult(false, null, default(Point));
        }

        public Point XGetContentPos()
        {
            return new Point(this.Padding.Left, this.Padding.Top);
        }

        #region Implement IPartContainer

        public List<Part> GetPartList()
        {
            return _partCollection.PartList;
        }

        /// <summary>
        /// 添加子组件
        /// </summary>
        /// <param name="part"></param>
        public void AddPart(UI.Part part)
        {
            _partCollection.Add(part);
            part.ParentPart = this;

            TabHeader header = new TabHeader(part);

            header.XHeaderBackgroundImage = this.XHeaderBackgroundImage;

            header.XHeaderFont = this.XHeaderFont;
            header.XHeaderFontSize = this.XHeaderFontSize;
            header.XHeaderForeground = this.XHeaderForeground;
            header.XHeaderHeight = this.XHeaderHeight;
            header.XHeaderPadding = this.XHeaderPadding;
            header.XHeaderWidth = this.XHeaderWidth;

            header.XActiveHeaderBackgroundImage = this.XActiveHeaderBackgroundImage;
            header.XActiveHeaderFont = this.XActiveHeaderFont;
            header.XActiveHeaderFontSize = this.XActiveHeaderFontSize;
            header.XActiveHeaderForeground = this.XActiveHeaderForeground;
            header.XActiveHeaderHeight = this.XActiveHeaderHeight;
            header.XActiveHeaderPadding = this.XActiveHeaderPadding;
            header.XActiveHeaderWidth = this.XActiveHeaderWidth;

            _headers.Add(header);
            if (_headers.Count > 1)
            {
                // 设置间距，第一个tab页不设置
                header.Margin = new Thickness(this.XHeaderSpacing, 0, -this.XHeaderSpacing, 0);
            }

            header.Click += header_Click;
            _stackPanel.Children.Add(header);
            Canvas.SetZIndex(header, _stackPanel.Children.Count - 1);
        }

        public void XRemovePart(UI.Part part)
        {
            TabHeader tmp = null;
            foreach (var item in _stackPanel.Children)
            {
                if (item is TabHeader)
                {
                    if ((item as TabHeader).Part == part)
                    {
                        tmp = (TabHeader)item;
                    }
                }
            }
            if (tmp != null)
            {
                _stackPanel.Children.Remove(tmp);
            }
            _partCollection.Remove(part);
        }

        /// <summary>
        /// 获取子组件
        /// </summary>
        /// <param name="partName"></param>
        /// <param name="isRecursive">是否递归</param>
        /// <returns></returns>
        public Part GetChildPart(string partName, bool isRecursive)
        {
            return _partCollection.GetChildPart(partName, isRecursive);
        }

        /// <summary>
        /// 根据类型来获取组件里包含的子组件
        /// </summary>
        /// <param name="isRecursive"></param>
        /// <returns></returns>
        public List<T> GetChildPartByType<T>(bool isRecursive)
        {
            return _partCollection.GetChildPartByType<T>(isRecursive);
        }

        public bool ValidateChildType(Type childType)
        {
            if (childType != typeof(ScenePart))
            {
                return true;
            }
            return false;
        }

        /// <summary>
        /// 获取实际的可存放组件的容器控件
        /// </summary>
        /// <returns></returns>
        public UIElement GetContentContainer()
        {
            return this._stackPanel;
        }

        public void BringPartTo(Part part, int index)
        {
            XRemovePart(part);
            _partCollection.Insert(part, index);
            part.ParentPart = this;

            TabHeader header = new TabHeader(part);

            header.XHeaderBackgroundImage = this.XHeaderBackgroundImage;

            header.XHeaderFont = this.XHeaderFont;
            header.XHeaderFontSize = this.XHeaderFontSize;
            header.XHeaderForeground = this.XHeaderForeground;
            header.XHeaderHeight = this.XHeaderHeight;
            header.XHeaderPadding = this.XHeaderPadding;
            header.XHeaderWidth = this.XHeaderWidth;

            header.XActiveHeaderBackgroundImage = this.XActiveHeaderBackgroundImage;
            header.XActiveHeaderFont = this.XActiveHeaderFont;
            header.XActiveHeaderFontSize = this.XActiveHeaderFontSize;
            header.XActiveHeaderForeground = this.XActiveHeaderForeground;
            header.XActiveHeaderHeight = this.XActiveHeaderHeight;
            header.XActiveHeaderPadding = this.XActiveHeaderPadding;
            header.XActiveHeaderWidth = this.XActiveHeaderWidth;

            _headers.Insert(index, header);
            if (_headers.Count > 1)
            {
                // 设置间距，第一个tab页不设置
                header.Margin = new Thickness(this.XHeaderSpacing, 0, -this.XHeaderSpacing, 0);
            }

            header.Click += header_Click;
            _stackPanel.Children.Insert(index, header);
        }

        public int GetPartIndex(Part part)
        {
            if (part != null)
            {
                if (_partCollection != null && _partCollection.Count > 0)
                {
                    for (int index = 0; index < _partCollection.Count; index++)
                    {
                        if (_partCollection[index] == part)
                        {
                            return index;
                        }
                    }
                }
            }
            return -1;
        }

        public int GetSendToBackIndex(Part part)
        {
            return 0;
        }

        public int GetBringToFrontIndex(Part part)
        {
            return _partCollection.Count - 1;
        }
        public int GetForwardIndex(Part part)
        {
            int index = GetPartIndex(part);
            return index < _partCollection.Count - 1 ? index + 1 : index;
        }

        public int GetBackwardIndex(Part part)
        {
            int index = GetPartIndex(part);
            return index > 0 ? index - 1 : index;
        }

        public Tuple<Point?, Point?, byte> GetAlignLinePoint(Part part, double left = -1, double top = -1, double right = -1, double bottom = -1)
        {
            //00表示left和top，01表示right和top，10表示left和bottom，11表示right和bottom
            byte bDirection = 0;
            Point? leftOrRight = null;
            Point? topOrBottom = null;
            double minOffsetX = double.MaxValue;
            double minOffsetY = double.MaxValue;
            for (int index = 0; index < _partCollection.Count; index++)
            {
                Part destPart = _partCollection[index];
                if (destPart != part)
                {
                    if (left >= 0)
                    {
                        if (Math.Abs(destPart.XLeft - left) < 2 && Math.Abs(destPart.XLeft - left) < minOffsetX)
                        {
                            minOffsetX = Math.Abs(destPart.XLeft - left);
                            leftOrRight = new Point(destPart.XLeft, destPart.XTop + destPart.XHeight / 2);
                            bDirection &= 2;
                        }
                        else if (Math.Abs(destPart.XLeft + destPart.XWidth - left) < 2 && Math.Abs(destPart.XLeft + destPart.XWidth - left) < minOffsetX)
                        {
                            minOffsetX = Math.Abs(destPart.XLeft + destPart.XWidth - left);
                            leftOrRight = new Point(destPart.XLeft + destPart.XWidth, destPart.XTop + destPart.XHeight / 2);
                            bDirection &= 2;
                        }
                    }
                    if (top >= 0)
                    {
                        if (Math.Abs(destPart.XTop - top) < 2 && Math.Abs(destPart.XTop - top) < minOffsetY)
                        {
                            minOffsetY = Math.Abs(destPart.XTop - top);
                            topOrBottom = new Point(destPart.XLeft + destPart.XWidth / 2, destPart.XTop);
                            bDirection &= 1;
                        }
                        else if (Math.Abs(destPart.XTop + destPart.XHeight - top) < 2 && Math.Abs(destPart.XTop + destPart.XHeight - top) < minOffsetY)
                        {
                            minOffsetY = Math.Abs(destPart.XTop + destPart.XHeight - top);
                            topOrBottom = new Point(destPart.XLeft + destPart.XWidth / 2, destPart.XTop + destPart.XHeight);
                            bDirection &= 1;
                        }
                    }
                    if (right >= 0)
                    {
                        if (Math.Abs(destPart.XLeft - right) < 2 && Math.Abs(destPart.XLeft - right) < minOffsetX)
                        {
                            minOffsetX = Math.Abs(destPart.XLeft - right);
                            leftOrRight = new Point(destPart.XLeft, destPart.XTop + destPart.XHeight / 2);
                            bDirection |= 1;
                        }
                        else if (Math.Abs(destPart.XLeft + destPart.XWidth - right) < 2 && Math.Abs(destPart.XLeft + destPart.XWidth - right) < minOffsetX)
                        {
                            minOffsetX = Math.Abs(destPart.XLeft + destPart.XWidth - right);
                            leftOrRight = new Point(destPart.XLeft + destPart.XWidth, destPart.XTop + destPart.XHeight / 2);
                            bDirection |= 1;
                        }
                    }
                    if (bottom >= 0)
                    {
                        if (Math.Abs(destPart.XTop - bottom) < 2 && Math.Abs(destPart.XTop - bottom) < minOffsetY)
                        {
                            minOffsetY = Math.Abs(destPart.XTop - bottom);
                            topOrBottom = new Point(destPart.XLeft + destPart.XWidth / 2, destPart.XTop);
                            bDirection |= 2;
                        }
                        else if (Math.Abs(destPart.XTop + destPart.XHeight - bottom) < 2 && Math.Abs(destPart.XTop + destPart.XHeight - bottom) < minOffsetY)
                        {
                            minOffsetY = Math.Abs(destPart.XTop + destPart.XHeight - bottom);
                            topOrBottom = new Point(destPart.XLeft + destPart.XWidth / 2, destPart.XTop + destPart.XHeight);
                            bDirection |= 2;
                        }
                    }
                }
            }
            return new Tuple<Point?, Point?, byte>(leftOrRight, topOrBottom, bDirection);
        }
        #endregion
    }
}
